﻿using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void DoSomething(string sParm)
        {
            long Result = 0;

            Console.WriteLine($"this is DoSomething Start  {Thread.CurrentThread.ManagedThreadId}");
            for (int i = 0; i < 1000000; i++)
            {
                Result += i;
            }
            Thread.Sleep(2000);
            Console.WriteLine($"this is Domething End {Thread.CurrentThread.ManagedThreadId}");
        }


        private void button1_Click(object sender, EventArgs e)
        {
            #region 同步
            /*
              Console.WriteLine("btnSync_Click同步方法  start");
            Action<string> action = this.DoSomething;
            action.Invoke("btnSync_Click");  //;利用委托调用Domething方法，这块实际上和直接调用Domething方法没什么区别
            Console.WriteLine("btnSync_Click同步方法  End");
             
             */
            #endregion

            #region 异步

            //Console.WriteLine("btn_Async_Click异步方法  start");
            //int P = 0;
            //AsyncCallback asyncCallback = t =>    //:t 参数实际上是委托的异步调用BeginInvoke返回的结果作为参数
            //{
            //    Console.WriteLine("在这里处理异步执行完成之后需要完成的业务操作");
            //    if (t.IsCompleted)
            //    {
            //        P = 1;
            //        Console.WriteLine($"P={P}");
            //    }
            //};

            //Action<string> action = this.DoSomething;
            ////IAsyncResult tr = action.BeginInvoke("btn_Async_Click", new AsyncCallback(UpdateInstanceP), null);
            //action.BeginInvoke("btn_Async_Click", asyncCallback, null);  //:lambala表达式方式
            //Console.WriteLine("btn_Async_Click异步方法  End");




            #endregion

            #region  判断加EndInvoke方式
            /*
            Stopwatch watchStop = new Stopwatch();
            watchStop.Start();
            Func<string, long> func = this.ReturnResult;
            IAsyncResult tr = func.BeginInvoke("", null, null);
            while (!tr.IsCompleted)
            {
                Thread.Sleep(200);  //:优点：1、边等待边操作，比如用户提示      2、不足点：可能存在误差，最多200ms
            }
            //tr.AsyncWaitHandle.WaitOne();  //:优点：1、等到异步完成，没有损耗   2、不足：没办法做提示
            //tr.AsyncWaitHandle.WaitOne(2000);  //:优点：1、最多等待2000ms,可以做超时处理

            long result = func.EndInvoke(tr);
            Console.WriteLine($"异步方法返回的结果值{result}");
            watchStop.Stop();
            Console.WriteLine("The second RunTime------watchStop-----:{0}", watchStop.ElapsedMilliseconds);
            */
            #endregion

            #region  EndInvoke方式
            //Stopwatch watchStop1 = new Stopwatch();
            //watchStop1.Start();
            //Func<string, long> func1 = this.ReturnResult;
            //IAsyncResult tr1 = func1.BeginInvoke("", null, null);
            //long result1 = func1.EndInvoke(tr1);
            //Console.WriteLine($"异步方法返回的结果值{result1}");
            //watchStop1.Stop();
            //Console.WriteLine("The second RunTime1-----------watchStop1----------:{0}", watchStop1.ElapsedMilliseconds);

            #endregion

            #region 回调方式获取结果
            Stopwatch watchStop2 = new Stopwatch();
            watchStop2.Start();
            AsyncCallback asyncCallback = t =>
            {
                System.Runtime.Remoting.Messaging.AsyncResult ar = (System.Runtime.Remoting.Messaging.AsyncResult)t;
                Func<string, long> del = (Func<string, long>)ar.AsyncDelegate;
                //回调方法中调用了EndInvoke
                long result3 = del.EndInvoke(t);
                Console.WriteLine($"异步方法返回的结果值{result3}");
                watchStop2.Stop();
                Console.WriteLine("The second RunTime1-----------watchStop2----------:{0}", watchStop2.ElapsedMilliseconds);
            };

            Func<string, long> func2 = this.ReturnResult;
            IAsyncResult tr2 = func2.BeginInvoke("", asyncCallback, null);
            while (!tr2.IsCompleted)
            {
                Console.WriteLine("gg");
            }
            if (tr2.IsCompleted)
            {
                Console.WriteLine("mm");
            }
            #endregion


        }

        private long ReturnResult(string arg)
        {
            long t = 0;
            for (long i = 0; i < 500000; i++)
            {
                t++;
            }
            return t;
        }

        private void button2_Click(object sender, EventArgs e)
        {

        }
    }
}
